package db

import (
	"fmt"
	"gitee.com/Hu-Lyndon/distill-resk/infra/utils"

	"github.com/go-xorm/xorm"
	"github.com/kataras/golog"
	"sync"
	"time"

	"github.com/go-xorm/core"

	_ "github.com/go-sql-driver/mysql"
)


type XormConfig struct {
	Db map[string]DBConfigInfo `toml:"db"`
}

type DBConfigInfo struct {
	Dialect         string `toml:"dialect"`
	User            string `toml:"user"`
	Password        string `toml:"password"`
	Host            string `toml:"host"`
	Port            int    `toml:"port"`
	Database        string `toml:"database"`
	Charset         string `toml:"charset"`
	ShowSql         bool   `toml:"showSql"`
	LogLevel        string `toml:"logLevel"`
	MaxOpenConns    int    `toml:"maxOpenConns"`
	MaxIdleConns    int    `toml:"maxIdleConns"`
	ConnMaxLifetime int64  `toml:"connMaxLifetime"`
	//Sslmode         string `toml:"sslmode"`
}

type RedisConfig struct {
	Addr      string `toml:"addr"`
	MaxIdle   int    `toml:"maxIdle"`
	MaxActive int    `toml:"maxActive"`
	Timeout   string `toml:"timeout"`
}


func GetConnURL(info *DBConfigInfo) (url string) {
	//db, err := gorm.Open("mysql", "user:password@/dbname?charset=utf8&parseTime=True&loc=Local")
	url = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s",
		info.User,
		info.Password,
		info.Host,
		info.Port,
		info.Database,
		info.Charset)
	//golog.Infof("@@@ DB conn==>> %s", url)
	return
}

type DBEngines struct {
	DbMasterConfigInfo *DBConfigInfo
	DbSlaveConfigInfo  *DBConfigInfo
	masterEngine       *xorm.Engine
	slaveEngine        *xorm.Engine
	lock               sync.Mutex
}

// 主库，单例
func (dbConfig *DBEngines) MasterEngine() *xorm.Engine {

	if dbConfig.masterEngine != nil {
		goto EXIST
	}

	dbConfig.lock.Lock()
	defer dbConfig.lock.Unlock()

	if dbConfig.masterEngine != nil {
		goto EXIST
	}

	dbConfig.createEngine(dbConfig.DbMasterConfigInfo, true)
	return dbConfig.masterEngine

EXIST:
	var err = dbConfig.masterEngine.Ping()
	if err != nil {
		golog.Errorf("@@@ 数据库 master 节点连接异常挂掉!! %s", err)
		dbConfig.createEngine(dbConfig.DbMasterConfigInfo, true)
	}
	return dbConfig.masterEngine
}

// 从库，单例
func (dbConfig *DBEngines) SlaveEngine() *xorm.Engine {

	if dbConfig.slaveEngine != nil {
		goto EXIST
	}

	dbConfig.lock.Lock()
	defer dbConfig.lock.Unlock()

	if dbConfig.slaveEngine != nil {
		goto EXIST
	}

	dbConfig.createEngine(dbConfig.DbSlaveConfigInfo, false)
	return dbConfig.slaveEngine

EXIST:
	var err = dbConfig.slaveEngine.Ping()
	if err != nil {
		golog.Errorf("@@@ 数据库 slave 节点连接异常挂掉!! %s", err)
		dbConfig.createEngine(dbConfig.DbSlaveConfigInfo, false)
	}
	return dbConfig.slaveEngine
}

func (dbConfig *DBEngines) createEngine(dbIndo *DBConfigInfo, isMaster bool) {
	engine, err := xorm.NewEngine(dbIndo.Dialect, GetConnURL(dbIndo))
	if err != nil {
		golog.Fatalf("@@@ 初始化数据库连接失败!! %s", err)
		return
	}
	//settings(engine, &dbIndo)

	engine.ShowSQL(dbIndo.ShowSql)
	engine.SetMapper(core.GonicMapper{})
	engine.SetTZLocation(utils.SysTimeLocation)
	if dbIndo.MaxIdleConns > 0 {
		engine.SetMaxIdleConns(dbIndo.MaxIdleConns)
	}
	if dbIndo.MaxOpenConns > 0 {
		engine.SetMaxOpenConns(dbIndo.MaxOpenConns)
	}

	if dbIndo.ConnMaxLifetime > 0 {
		engine.SetConnMaxLifetime(time.Duration(dbIndo.ConnMaxLifetime) * time.Second)
	}
	// 性能优化的时候才考虑，加上本机的SQL缓存
	//cacher := xorm.NewLRUCacher(xorm.NewMemoryStore(), 1000)
	//engine.SetDefaultCacher(cacher)

	if isMaster {
		dbConfig.masterEngine = engine
	} else {
		dbConfig.slaveEngine = engine
	}

}
